package com.ljx.recruitment.user.event.impl;

import com.ljx.recruitment.user.constant.TenantConstant;
import com.ljx.recruitment.user.domain.entity.*;
import com.ljx.recruitment.user.domain.vo.req.RoleToUserReq;
import com.ljx.recruitment.user.enums.CommonRoleEnum;
import com.ljx.recruitment.user.event.TenantSubmitEvent;
import com.ljx.recruitment.user.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
import org.springframework.util.DigestUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class TenantSubmitEventHandler {

    @Autowired
    private TenantService tenantService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private UserService userService;

    @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT, classes = TenantSubmitEvent.class, fallbackExecution = true)
    public void initTenant(TenantSubmitEvent event) {
        Tenant tenant = tenantService.getById(event.getTenantId());
        String tenantCode = tenant.getCode();
        List<String> roles = Arrays.asList(CommonRoleEnum.getAdminCode(tenantCode), CommonRoleEnum.getUserCode(tenantCode),
                CommonRoleEnum.getStaffCode(tenantCode), CommonRoleEnum.getHrCode(tenantCode));
        roles.forEach(item -> {
            saveRole(item, tenantCode);
        });
        initTenantAdmin(tenant);
    }

    private void initTenantAdmin(Tenant tenant) {
        String username = String.format(TenantConstant.initTenantAdminUsername, tenant.getCode());
        User user = new User(username, DigestUtils.md5DigestAsHex(DigestUtils.md5DigestAsHex(username.getBytes()).getBytes()), tenant.getId());
        userService.save(user);
        String roleName = CommonRoleEnum.getAdminCode(tenant.getCode());
        Role role = roleService.getByName(roleName);
        RoleToUserReq req = new RoleToUserReq();
        req.setUserId(user.getId());
        req.setRoleIds(Collections.singletonList(role.getId()));
        roleService.allocationToUser(req);
    }

    private void saveRole(String roleName, String tenantCode) {
        Role role = new Role(roleName);
        roleService.save(role);
        List<Long> permissionIds = permissionService.getPermissionByNames(CommonRoleEnum.initPermissionByRole(roleName))
                        .stream().map(Permission::getId).collect(Collectors.toList());
        roleService.saveRolePermissionsById(role.getId(), permissionIds);
        List<Long> menuIds = menuService.getMenuByCodes(CommonRoleEnum.initMenuByRole(roleName))
                .stream().map(Menu::getId).collect(Collectors.toList());
        roleService.saveRoleMenusById(role.getId(), menuIds);
    }

}
